
#include "Daemon.h"

namespace zg_util{

    /*子进程不处理SIGTERM信号*/
    void Daemon::set_child_sig() {
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIG_IGN;
        sigaction(SIGPIPE, &act, NULL);
        sigaction(SIGUSR1, &act, NULL);
//        act.sa_handler = signal_handler;
        act.sa_handler = SIG_DFL;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGTERM, &act, NULL);
    }
    void Daemon::set_father_sig() {
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIG_IGN;
        sigaction(SIGPIPE, &act, NULL);
        sigaction(SIGUSR1, &act, NULL);
        act.sa_handler = signal_handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGTERM, &act, NULL);
    }

    void Daemon::signal_handler(int sig)
    {
        switch (sig)
        {
            case SIGTERM:
                Daemon::app_shutdown = 1;
                break;
        }
    }
    void Daemon::Log(const char* log_str,...){
        int fd;
        time_t t;
        fd = open("daemon.log",O_WRONLY|O_CREAT|O_APPEND,0644);
        char log_buf[2048]={0};
        char temp[1024]={0};
        if(fd == -1)
            return;
        va_list arg;
        va_start( arg, log_str);
        memset(temp, 0x00,sizeof(temp));
        vsnprintf(temp, sizeof(temp)-1, log_str, arg );
        va_end( arg );
        snprintf(log_buf,sizeof(log_buf),"%s %s",DateTime::CurDateTimeStr().c_str(),temp);
        write(fd,log_buf,strlen(log_buf));
        write(fd,"\r\n",2);
        close(fd);
    }
    int Daemon::InitDaemon(int child_pro_count,int closefd,char* pwd){
        Daemon::set_father_sig();
        pid_t pid;
        pid = fork();
        if (pid == -1) {
            return -1;
        }
        if (pid > 0){
            exit(1);
        }
        if (setsid() == -1){
            exit(0);
        }
        if (pwd)
            chdir(pwd);
        if (closefd) {
            int i;
            for (i = 0; i < 3; ++i) {
                close(i);
                open("/dev/null", O_RDWR);
                dup(0);
                dup(0);
            }
            umask(0);
        }
        int num_childs=child_pro_count;
        if (num_childs > 0)
        {
            while (!Daemon::child && !Daemon::app_shutdown)
            {
                if (num_childs > 0)
                {
                    switch (fork())
                    {
                        case -1:
                            return -1;
                        case 0:
                            Daemon::child = 1;
                            //  Daemon::set_child_sig();
                            Log("create new child process pid=%d", getpid());
                            break;
                        default:
                            num_childs--;
                            break;
                    }
                }
                else
                {
                    int status;
                    if (-1 != wait(&status))
                    {
                        num_childs++;
                    }
                }
            }
            /*主进程退出*/
            if (!Daemon::child)
            {
                if (Daemon::app_shutdown)
                {
                    Log("master process exit");
                    exit(1);
                }
            }
        }
    }

    volatile sig_atomic_t Daemon::app_shutdown=0;
    volatile sig_atomic_t Daemon::child=0;
}